#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <unistd.h>

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;
 
int main(void)
{
	int ret = -1;
	// 1、使用socket()函数获取一个socket文件描述符
	int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if (-1 == sockfd)
	{
		printf("socket open err.");
		return -1;
	}
 
    // 2、绑定本地的相关信息，如果不绑定，则系统会随机分配一个端口号
    struct sockaddr_in local_addr = {0};
    local_addr.sin_family = AF_INET;                                //使用IPv4地址
    //local_addr.sin_addr.s_addr = inet_addr("192.168.0.107");        //本机IP地址
    local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    local_addr.sin_port = htons(8266);                             //端口
    bind(sockfd, (struct sockaddr*)&local_addr, sizeof(local_addr));//将套接字和IP、端口绑定
 
    // 3、等待接收对方发送的数据
    struct sockaddr_in recv_addr;
    socklen_t addrlen = sizeof(recv_addr);
    char recvbuf[1024] = {0};
   // char data_total[300000];
   char data_total[400000];
    //ret = recvfrom(sockfd, recvbuf, 1024, 0,(struct sockaddr*)&recv_addr,&addrlen);  //1024表示本次接收的最大字节数
    //ret = recvfrom(sockfd, data_total, 60000, 0,(struct sockaddr*)&recv_addr,&addrlen);
    //printf("[recv from %s:%d]%s \n",inet_ntoa(*(struct in_addr*)&recv_addr.sin_addr.s_addr),ntohs(recv_addr.sin_port),recvbuf);
     //int imgFlag = 12345;
     int imgFlag = 11111;
     //int img_head[1];
     int img_head[4];
     int recvbytes = recvfrom(sockfd, (char*)img_head, 24, 0, (struct sockaddr*)&recv_addr, &addrlen);
        int imgLen = img_head[1];
        int imgPackUnit = img_head[2];
        int imgpackNum = img_head[3];
        int imgtimestampsec = img_head[4];
       int imgtimestampnsec = img_head[5];
        int recvd_size = 0;

     if(img_head[0]==imgFlag)   //只有这个图像标志位是预期的值，才会运行后面接收图像的代码，才会显示图像，所以只要运行后图像显示出来了，说明前面的这个图像标志位是接收到了的，是准确的。
{
    printf("imgFlag:%d \n",img_head[0]);
    printf("imgPackUnit:%d \n",img_head[2]);
    printf("imgtimestampsec:%d \n",img_head[4]);
    printf("imgtimestampnsec:%d \n",img_head[5]);
    int i1=0;
    //for(i1=0;i1<5;i1++)
     for(i1=0;i1<imgpackNum;i1++)
      {
        //int recvpack = recvfrom(sockfd, data_total+i1*60000, 60000, 0,(struct sockaddr*)&recv_addr,&addrlen);
        int recvpack = recvfrom(sockfd, data_total+i1*imgPackUnit, imgPackUnit, 0,(struct sockaddr*)&recv_addr,&addrlen);
        recvd_size += recvpack;
        printf("recvd_size:%d \n",recvd_size);
      }
      //printf("recvd_size:%d \n",recvd_size);
    //如果接收大小出问题是可能出问题的。实际接了多少，下面就值年写多少否则图像弹不出来。就是实际data_total接了多少数据。所以下面改为recvd_size，原本的接收程序也是这么写了，可能也是有道理的。
    //Mat image = imdecode(Mat(1, 300000, CV_8UC1, data_total), IMREAD_COLOR);   //这里数字填大了就会出现段错误。错了，段错误不是这里引起了，是send端的存储数组比图像大小小了会出现段错误。
    Mat image = imdecode(Mat(1, recvd_size, CV_8UC1, data_total), IMREAD_COLOR);   //这里数字填大了就会出现段错误。错了，段错误不是这里引起了，是send端的存储数组比图像大小小了会出现段错误。
    imshow("recv",image);
    waitKey(0); 
    //printf("recvd_size:%d \n",recvd_size);
}
    // 4. 关闭套接字
    close(sockfd);
}
